﻿using LightCAD.Core.Elements;
using LightCAD.Core;
using LightCAD.Runtime;
using SkiaSharp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace LightCAD.Drawing
{
    public class DimRotatedAction : ElementAction
    {
        private DimRotatedAction() { }

        public DimRotatedAction(DocumentRuntime docRt)
            : base(docRt)
        {
            docRt.CommandCtrl.WriteInfo("命令：DimLinear");
        }


        private static readonly LcCreateMethod[] CreateMethods;

        static DimRotatedAction()
        {
            CreateMethods = new LcCreateMethod[1];
            CreateMethods[0] = new LcCreateMethod()
            {
                Name = "2P",
                Description = "两点创建线性标注",
                Steps = new LcCreateStep[]
                                                   {
                                                       new LcCreateStep { Name = "Step0", Options = "指定第一个尺寸界线原点或 <选择对象>:" },
                                                       new LcCreateStep { Name = "Step1", Options = "指定第二条尺寸界线原点:" },
                                                       new LcCreateStep { Name = "Step2", Options = "指定尺寸线位置或\r\n[多行文字(M)/文字(T)/角度(A)/水平(H)/垂直(V)/旋转(R)]:" },
                                                   }
            };
        }

        internal static void Initilize()
        {
            ElementActions.DimRotated = new DimRotatedAction();
            LcDocument.ElementActions.Add(BuiltinElementType.DimRotated, ElementActions.DimRotated);
        }

        private List<Vector2d> points;

        private Vector2d? firstPoint { get; set; }

        private Vector2d? secondPoint { get; set; }
        private Vector2d? thirdPoint { get; set; }
        private PointInputer inputer { get; set; }


        public async void ExecCreate(string[] args = null)
        {
            DocumentManager.CurrentRecorder.BeginAction("DimLinear");

            this.points = new List<Vector2d>();
            this.StartCreating();
            this.inputer = new PointInputer(this.docRt);
            var ElementInputer = new ElementInputer(this.docRt);
            var curMethod = CreateMethods[0];

        Step0:
            var step0 = curMethod.Steps[0];
            var result0 = await inputer.Execute(step0.Options);
            //var result0 = await inputer.Execute(step0.Options);

            if (inputer.isCancelled)
            {
                this.Cancel();
                goto End;
            }

            // zcb: 增加Res0为空的判定
            if (result0 == null)
            {
                this.Cancel();
                goto End;
            }

            if (result0.Value == null)
            {
                if (result0.Option != null)
                {
                    //TODO:AutoCAD画线输入一个数字，是怎么确定点的？
                }
                else
                {
                    goto Step1;
                }
            }

            this.firstPoint = (Vector2d)result0.Value;

        Step1:
            var step1 = curMethod.Steps[1];
            if (this.points.Count >= 2)
            {
                step1 = curMethod.Steps[2];
            }

            var result1 = await inputer.Execute(step1.Options);
            if (inputer.isCancelled)
            {
                this.Cancel();
                goto End;
            }

            if (result1.Value == null)
            {
                if (result1.Option == "U") { }
                else if (result1.Option == "C")
                {
                    goto End;
                }
                else if (result1.Option == " ")
                {
                    goto End;
                }
                else if (result1.Option != null)
                {
                    docRt.CommandCtrl.WriteInfo(SR.PointError);
                    goto Step2;
                    //TODO:AutoCAD画线输入一个数字，是怎么确定点的？
                }
                else
                {
                    goto Step2;
                }
            }
            this.secondPoint = (Vector2d)result1.Value;
        //var lcLine = docRt.Document.CreateObject<DimRotated>(firstPoint.Value, secondPoint.Value);
        //Draw(canvas, lcLine);
        Step2:
            var step2 = curMethod.Steps[2];
            var result2 = await inputer.Execute(step2.Options);
            //var result0 = await inputer.Execute(step0.Options);

            if (inputer.isCancelled)
            {
                this.Cancel();
                goto End;
            }

            // zcb: 增加Res0为空的判定
            if (result2 == null)
            {
                this.Cancel();
                goto End;
            }

            if (result2.Value == null)
            {
                if (result2.Option != null)
                {
                    //TODO:AutoCAD画线输入一个数字，是怎么确定点的？
                }
                else
                {
                    goto Step2;
                }
            }

            this.thirdPoint = (Vector2d)result2.Value;
            var lcLine = docRt.Document.CreateObject<DimRotated>(firstPoint.Value, secondPoint.Value, thirdPoint.Value);
            points.Add(firstPoint.Value);
            points.Add(secondPoint.Value);
            points.Add(thirdPoint.Value);
            firstPoint = secondPoint;

            CreateDimElements(lcLine);
        End:
            this.inputer = null;
            this.EndCreating();

            if (this.points.Count > 0)
            {
                DocumentManager.CurrentRecorder.EndAction();
            }
            else
            {
                DocumentManager.CurrentRecorder.CancleAction();
            }
        }

        public override void Cancel()
        {
            base.Cancel();
            this.vportRt.SetCreateDrawer(null);
        }
        public void CreateDimElements(LcElement lcElement)
        {
            this.docRt.Document.ModelSpace.InsertElement(lcElement);
        }
        bool isDraw = true;
        public override void DrawAuxLines(SKCanvas canvas)
        {

            if (firstPoint != null && isDraw)
            {
                isDraw = true;
                var mp = this.vportRt.PointerMovedPosition.ToVector2d();
                var wcs_mp = this.vportRt.ConvertScrToWcs(mp);
                DrawAuxLine(canvas, firstPoint.Value, wcs_mp);
            }
            if (secondPoint != null)
            {
                isDraw = false;
                var mp = this.vportRt.PointerMovedPosition.ToVector2d();
                var wcs_mp = this.vportRt.ConvertScrToWcs(mp);
                Vector2d newWCS_mp = new Vector2d(firstPoint.Value.X, wcs_mp.Y);
                Vector2d newWCS_mp2 = new Vector2d(secondPoint.Value.X, wcs_mp.Y);
                DrawAuxLine(canvas, firstPoint.Value, newWCS_mp);
                DrawAuxLine(canvas, secondPoint.Value, newWCS_mp2);
                DrawAuxLine(canvas, newWCS_mp, newWCS_mp2);
            }
        }

        //public override void DrawTemp(SKCanvas canvas)
        //{
        //    for (var i = 1; i < this.points.Count; i++)
        //    {
        //        var pre = this.points[i - 1];
        //        var p = this.points[i];
        //        DrawLine(canvas, pre, p);
        //    }
        //}
        private void DrawAuxLine(SKCanvas canvas, Vector2d p0, Vector2d p1)
        {
            var sk_pre = this.vportRt.ConvertWcsToScr(p0).ToSKPoint();
            var sk_p = this.vportRt.ConvertWcsToScr(p1).ToSKPoint();
            //辅助元素的颜色 
            canvas.DrawLine(sk_pre, sk_p, Constants.auxElementPen);
            //辅助曲线的颜色，包括辅助长度，辅助角度等
        }

        public override void Draw(SKCanvas canvas, LcElement element, Matrix3d matrix)
        {
            var dimRotated = element as DimRotated;
            var first = matrix.MultiplyPoint(dimRotated.First);
            var second = matrix.MultiplyPoint(dimRotated.Second);
            var third = matrix.MultiplyPoint(new Vector2d(dimRotated.First.X, dimRotated.Third.Y));

            var firstStart = this.vportRt.ConvertWcsToScr(first).ToSKPoint();
            var secondStart = this.vportRt.ConvertWcsToScr(second).ToSKPoint();
            var thirdStart = this.vportRt.ConvertWcsToScr(third).ToSKPoint();

            var firstE = matrix.MultiplyPoint(new Vector2d(dimRotated.First.X, dimRotated.Third.Y));
            var secondE = matrix.MultiplyPoint(new Vector2d(dimRotated.Second.X, dimRotated.Third.Y));
            var thirdE = matrix.MultiplyPoint(new Vector2d(dimRotated.Second.X, dimRotated.Third.Y));

            var firstEnd = this.vportRt.ConvertWcsToScr(firstE).ToSKPoint();
            var secondEnd = this.vportRt.ConvertWcsToScr(secondE).ToSKPoint();
            var thirdEnd = this.vportRt.ConvertWcsToScr(thirdE).ToSKPoint();

            var pen = this.GetDrawPen(dimRotated);
            if (pen == Constants.defaultPen)
            {
                //TODO:这里可以考虑将实线用颜色做KEY，对SKPaint进行缓存
                using (var elePen = new SKPaint { Color = new SKColor(element.GetColorValue()), IsStroke = true })
                {
                    canvas.DrawLine(firstStart, firstEnd, elePen);
                    canvas.DrawLine(secondStart, secondEnd, elePen);
                    canvas.DrawLine(thirdStart, thirdEnd, elePen);
                    canvas.DrawText(dimRotated.Length.ToString(), (thirdStart.X + thirdEnd.X) / 2, (thirdStart.Y + thirdEnd.Y) / 2, elePen);
                }
            }
            else
            {
                canvas.DrawLine(firstStart, firstEnd, pen);
                canvas.DrawLine(secondStart, secondEnd, pen);
                canvas.DrawLine(thirdStart, thirdEnd, pen);
                canvas.DrawText(dimRotated.Length.ToString(), (thirdStart.X + thirdEnd.X) / 2, (thirdStart.Y + thirdEnd.Y) / 2, pen);
            }

            #region
            var path = DrawArrow(third, thirdE);
            var path2 = DrawArrow(thirdE, third);
            using (var elePen = new SKPaint { Color = new SKColor(element.GetColorValue()), IsStroke = true })
            {
                //elePen.Color = SKColors.Red;
                elePen.Style = SKPaintStyle.Fill;
                elePen.IsAntialias = true;
                elePen.StrokeWidth = 2;
                //绘制路径
                canvas.DrawPath(path, elePen);
                canvas.DrawPath(path2, elePen);
            }
            
            //using (var elePen = new SKPaint { Color = new SKColor(element.GetColorValue()), IsStroke = true })
            //{
            //    //elePen.Color = SKColors.Red;
            //    elePen.Style = SKPaintStyle.Fill;
            //    elePen.IsAntialias = true;
            //    elePen.StrokeWidth = 2;
            //    //绘制路径
            //    canvas.DrawPath(path2, elePen);
            //}
            #endregion
        }

        public override ControlGrip[] GetControlGrips(LcElement element)
        {
            var dimRotated = element as DimRotated; //getHel
            var grips = new List<ControlGrip>();
            var gripFirst = new ControlGrip
            {
                Element = dimRotated,
                Name = "First",
                Position = dimRotated.First
            };
            grips.Add(gripFirst);
            var gripSecond = new ControlGrip
            {
                Element = dimRotated,
                Name = "Second",
                Position = dimRotated.Second
            };
            grips.Add(gripSecond);
            var gripThird = new ControlGrip
            {
                Element = dimRotated,
                Name = "Third",
                Position = new Vector2d(dimRotated.First.X, dimRotated.Third.Y)
            };
            grips.Add(gripThird);
            var gripFourth = new ControlGrip
            {
                Element = dimRotated,
                Name = "Fourth",
                Position = new Vector2d(dimRotated.Second.X, dimRotated.Third.Y)
            };
            grips.Add(gripFourth);
            var gripFifth = new ControlGrip
            {
                Element = dimRotated,
                Name = "Fifth",
                Position = new Vector2d((dimRotated.First.X + dimRotated.Second.X)/2, dimRotated.Third.Y)
            };
            grips.Add(gripFifth);
            return grips.ToArray();
        }

        //public override void CreateElement(LcElement element, Matrix3d matrix)
        //{
        //    var line = element as LcLine;
        //    this.vportRt.ActiveElementSet.AddLine(matrix.MultiplyPoint(line.Start), matrix.MultiplyPoint(line.End));
        //}

        //public override void CreateElement(LcElement element, Vector2d basePoint, double scaleFactor)
        //{
        //    var line = element as LcLine;
        //    Matrix3d matrix3 = Matrix3d.Scale(scaleFactor, basePoint);
        //    this.vportRt.ActiveElementSet.AddLine(matrix3.MultiplyPoint(line.Start), matrix3.MultiplyPoint(line.End));
        //}

        //public override void CreateElement(LcElement element, Vector2d basePoint, Vector2d scaleVector)
        //{
        //    var line = element as LcLine;
        //    Matrix3d matrix3 = Matrix3d.Scale(scaleVector, basePoint);
        //    this.vportRt.ActiveElementSet.AddLine(matrix3.MultiplyPoint(line.Start), matrix3.MultiplyPoint(line.End));
        //}

        private string _gripName;

        private Vector2d _position;

        private DimRotated _dimRotated;

        public override void SetDragGrip(LcElement element, string gripName, Vector2d position, bool isEnd)
        {
            var dimRotated = element as DimRotated;
            _dimRotated = dimRotated;
            if (!isEnd)
            {
                _gripName = gripName;
                _position = position;
            }
            else
            {
                if (gripName == "First")
                    dimRotated.Set(first: position);
                else if (gripName == "Second")
                {
                    dimRotated.Set(second: position);
                }
                else if (gripName == "Fifth")
                {
                    dimRotated.Set(third: position);
                }
            }
            //  DocumentManager.CurrentRecorder.EndAction();
        }
        public override void DrawDragGrip(SKCanvas canvas)
        {
            if (_dimRotated == null) return;

            var first = this.vportRt.ConvertWcsToScr(_dimRotated.First);
            if (_gripName == "Second")
                first = this.vportRt.ConvertWcsToScr(_position);

            var second = this.vportRt.ConvertWcsToScr(_dimRotated.Second);
            if (_gripName == "First")
                second = this.vportRt.ConvertWcsToScr(_position);
            var third = this.vportRt.ConvertWcsToScr(_dimRotated.Third);

            var fifth = this.vportRt.ConvertWcsToScr(new Vector2d((first.X + second.X) / 2, third.Y));
            if (_gripName == "Fifth")
            {
                fifth = this.vportRt.ConvertWcsToScr(_position);
                canvas.DrawLine(fifth.ToSKPoint(), new Vector2d((first.X + second.X) / 2, third.Y).ToSKPoint(), Constants.draggingPen);
                canvas.DrawLine(first.ToSKPoint(), new Vector2d(first.X, fifth.Y).ToSKPoint(), Constants.draggingPen);
                canvas.DrawLine(second.ToSKPoint(), new Vector2d(second.X, fifth.Y).ToSKPoint(), Constants.draggingPen);
                canvas.DrawLine(new Vector2d(first.X, fifth.Y).ToSKPoint(), new Vector2d(second.X, fifth.Y).ToSKPoint(), Constants.draggingPen);
            }
            if (_gripName == "Second" || _gripName == "First")
            {
                canvas.DrawLine(first.ToSKPoint(), second.ToSKPoint(), Constants.draggingPen);
                canvas.DrawLine(new Vector2d(first.X, third.Y).ToSKPoint(), new Vector2d(second.X, third.Y).ToSKPoint(), Constants.draggingPen);
            }

        }
        private SKPath DrawArrow(Vector2d start, Vector2d end, double extraAngle = 0)
        {
            LcLine lcline = new LcLine();
            lcline.Start = start;
            lcline.End = end;
            var radian = lcline.Angle;

            var startve = new Vector2d(lcline.Start.X, lcline.Start.Y);
            var arrowtwove = new Vector2d(lcline.Start.X + 100, lcline.Start.Y + 30);
            var arrowendve = new Vector2d(lcline.Start.X + 100, lcline.Start.Y - 30);
            var angle = Utils.RadianToDegree(radian) + extraAngle;
            arrowtwove = Vector2d.Rotate(arrowtwove, startve, angle);
            arrowendve = Vector2d.Rotate(arrowendve, startve, angle);

            var pointone = this.vportRt.ConvertWcsToScr(startve).ToSKPoint();
            var pointtwo = this.vportRt.ConvertWcsToScr(arrowtwove).ToSKPoint();
            var pointthree = this.vportRt.ConvertWcsToScr(arrowendve).ToSKPoint();

            var path = new SKPath();
            path.FillType = SKPathFillType.EvenOdd;
            //外圈 顺时针
            path.MoveTo((float)pointone.X, (float)pointone.Y);    //起点
            path.LineTo((float)pointtwo.X, (float)pointtwo.Y);
            path.LineTo((float)pointthree.X, (float)pointthree.Y);
            path.Close();
            return path;
        }

        public void Draw(SKCanvas canvas, LcElement element)
        {
            var dimRotated = element as DimRotated;
            var firstStart = this.vportRt.ConvertWcsToScr(dimRotated.First).ToSKPoint();
            var secondStart = this.vportRt.ConvertWcsToScr(dimRotated.Second).ToSKPoint();
            var thirdStart = this.vportRt.ConvertWcsToScr(new Vector2d(dimRotated.First.X, dimRotated.Third.Y)).ToSKPoint();

            var firstEnd = this.vportRt.ConvertWcsToScr(new Vector2d(dimRotated.First.X, dimRotated.Third.Y)).ToSKPoint();
            var secondEnd = this.vportRt.ConvertWcsToScr(new Vector2d(dimRotated.Second.X, dimRotated.Third.Y)).ToSKPoint();
            var thirdEnd = this.vportRt.ConvertWcsToScr(new Vector2d(dimRotated.Second.X, dimRotated.Third.Y)).ToSKPoint();
            var pen = this.GetDrawPen(dimRotated);
            if (pen == Constants.defaultPen)
            {
                //TODO:这里可以考虑将实线用颜色做KEY，对SKPaint进行缓存
                using (var elePen = new SKPaint { Color = new SKColor(element.GetColorValue()), IsStroke = true })
                {
                    canvas.DrawLine(firstStart, firstEnd, elePen);
                    canvas.DrawLine(secondStart, secondEnd, elePen);
                    canvas.DrawLine(thirdStart, thirdEnd, elePen);
                    canvas.DrawText(dimRotated.Length.ToString(), (thirdStart.X + thirdEnd.X) / 2, (thirdStart.Y + thirdEnd.Y) / 2, elePen);
                }
            }
            else
            {
                canvas.DrawLine(firstStart, firstEnd, pen);
                canvas.DrawLine(firstStart, firstEnd, pen);
                canvas.DrawLine(firstStart, firstEnd, pen);
                canvas.DrawText(dimRotated.Length.ToString(), (thirdStart.X + thirdEnd.X) / 2, (thirdStart.Y + thirdEnd.Y) / 2, pen);
            }

            #region
            //var path = DrawArrow(dimRotated.First, dimRotated.Second);
            //using (var elePen = new SKPaint { Color = new SKColor(element.GetColorValue()), IsStroke = true })
            //{
            //    //elePen.Color = SKColors.Red;
            //    elePen.Style = SKPaintStyle.StrokeAndFill;
            //    elePen.IsAntialias = true;
            //    elePen.StrokeWidth = 2;
            //    //绘制路径
            //    canvas.DrawPath(path, elePen);
            //}
            //var path2 = DrawArrow(dimRotated.Second, dimRotated.First);
            //using (var elePen = new SKPaint { Color = new SKColor(element.GetColorValue()), IsStroke = true })
            //{
            //    //elePen.Color = SKColors.Red;
            //    elePen.Style = SKPaintStyle.StrokeAndFill;
            //    elePen.IsAntialias = true;
            //    elePen.StrokeWidth = 2;
            //    //绘制路径
            //    canvas.DrawPath(path2, elePen);
            //}
            #endregion
        }
        //public override List<PropertyObserver> GetPropertyObservers()
        //{
        //    return new List<PropertyObserver>()
        //               {
        //                   new PropertyObserver()
        //                       {
        //                           Name = "StartX",
        //                           DisplayName = "起点 X 坐标",
        //                           Getter = (ele) => (ele as DimRotated).Start.X,
        //                           Setter = (ele, value) =>
        //                               {
        //                                   var line = (ele as DimRotated);
        //                                   var x = Convert.ToDouble(value);
        //                                   var sp = new Vector2d(x, line.Start.Y);
        //                                   line.Set(start: sp);
        //                               }
        //                       },
        //                   new PropertyObserver()
        //                       {
        //                           Name = "StartY",
        //                           DisplayName = "起点 Y 坐标",
        //                           Getter = (ele) => (ele as DimRotated).Start.Y,
        //                           Setter = (ele, value) =>
        //                               {
        //                                   var line = (ele as DimRotated);
        //                                   var y = Convert.ToDouble(value);
        //                                   var sp = new Vector2d(line.Start.X, y);
        //                                   line.Set(start: sp);
        //                               }
        //                       },
        //                   new PropertyObserver()
        //                       {
        //                           Name = "EndX",
        //                           DisplayName = "端点 X 坐标",
        //                           Getter = (ele) => (ele as LcLine).End.X,
        //                           Setter = (ele, value) =>
        //                               {
        //                                   var line = (ele as LcLine);
        //                                   var x = Convert.ToDouble(value);
        //                                   var ep = new Vector2d(x, line.End.Y);
        //                                   line.Set(end: ep);
        //                               }
        //                       },
        //                   new PropertyObserver()
        //                       {
        //                           Name = "EndY",
        //                           DisplayName = "端点 Y 坐标",
        //                           Getter = (ele) => (ele as LcLine).End.Y,
        //                           Setter = (ele, value) =>
        //                               {
        //                                   var line = (ele as LcLine);
        //                                   var y = Convert.ToDouble(value);
        //                                   var ep = new Vector2d(line.End.X, y);
        //                                   line.Set(end: ep);
        //                               }
        //                       },
        //                   new PropertyObserver()
        //                       {
        //                           Name = "DeltaX",
        //                           DisplayName = "增量X",
        //                           Getter = (ele) => (ele as LcLine).DeltaX
        //                       },
        //                   new PropertyObserver()
        //                       {
        //                           Name = "DeltaY",
        //                           DisplayName = "增量Y",
        //                           Getter = (ele) => (ele as LcLine).DeltaY
        //                       },
        //                   new PropertyObserver()
        //                       {
        //                           Name = "Length",
        //                           DisplayName = "长度",
        //                           Getter = (ele) => (ele as LcLine).Length
        //                       },
        //                   new PropertyObserver()
        //                       {
        //                           Name = "Angle",
        //                           DisplayName = "角度",
        //                           Getter = (ele) => (ele as LcLine).Angle * 180 / Math.PI
        //                       }
        //               };
        //}
    }
}
